/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package libsvm;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author kiakaku
 */
public class ChuanHoaFileHuanLuyen extends Thread {

    public List<Word> dict;
    public List<String> wordString;
    public int soVanBanHuanLuyen = 600;

    /*********************************************************
     *  CHÚ Ý   :  Khi muốn dùng lớp này để chuẩn hóa tập test 
     * với 300 ví dụ thì phải sửa thuộc tính soVanBanHuanLuyen
     * *******************************************************
     */
    public ChuanHoaFileHuanLuyen() {
        this.dict = new ArrayList<Word>();
        this.wordString = new ArrayList<String>();
    }

    public ChuanHoaFileHuanLuyen(int soVanBanHuanLuyen) {
        this.dict = new ArrayList<Word>();
        this.wordString = new ArrayList<String>();
        this.soVanBanHuanLuyen = soVanBanHuanLuyen;
    }

    public void readDiction() {
        String pathFile = Const.DICT_WITHOUT_STOP;
        try {
            FileReader fr = new FileReader(pathFile);
            BufferedReader reader = new BufferedReader(fr);
            String line = null;
            while ((line = reader.readLine()) != null) {
                dict.add(new Word(line));
                wordString.add(line);
            }
            reader.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Khong doc duoc tư dien !");
        }
    }

    public void docNhieuFileHuanLuyen(String folderName, String firstNamFile, int soTaiLieu) {
        String file = "";
        for (int i = 1; i <= soTaiLieu; i++) {
            file = folderName + firstNamFile + i + ".txt";
            doc1FileHuanLuyen(file);
        }
    }

    public int doc1FileHuanLuyen(String file) {
        List<String> abc = new ArrayList<String>();
        abc.clear();
//        this.soVanBanHuanLuyen++;
        int tongSoTuTrongMotVanBan = 0;
        {
            try {
                FileReader fr = new FileReader(file);
                BufferedReader reader = new BufferedReader(fr);
                String line = null;
                int idWord = 0;
                while ((line = reader.readLine()) != null) { //lấy tổng số từ tồn tại trong từ điển có trong văn bản
                    idWord = wordString.indexOf(layTuTu1Dong(line).word);
                    // chỉ lấy những từ có nghĩa(nằm trong file fileChuan.txt)và có số lần xuất hiện trong văn bản là >=2 và <=10
                    if (idWord != -1
                            && layTuTu1Dong(line).soLanXuatHienTrong1VanBan >= Const.SO_LAN_XUAT_HIEN_MIN
                            && layTuTu1Dong(line).soLanXuatHienTrong1VanBan <= Const.SO_LAN_XUAT_HIEN_MAX) {
                        tongSoTuTrongMotVanBan += layTuTu1Dong(line).soLanXuatHienTrong1VanBan;
                    }
                }
                reader.close();
                fr = new FileReader(file);
                reader = new BufferedReader(fr);
                StringBuilder outText = new StringBuilder();
                idWord = 0;
                while ((line = reader.readLine()) != null) {
                    idWord = wordString.indexOf(layTuTu1Dong(line).word.toLowerCase());
                    // chỉ lấy những từ có nghĩa(nằm trong file fileChuan.txt) và có số lần xuất hiện trong văn bản là >=2 và <=10
                    if (idWord != -1
                            && layTuTu1Dong(line).soLanXuatHienTrong1VanBan >= Const.SO_LAN_XUAT_HIEN_MIN
                            && layTuTu1Dong(line).soLanXuatHienTrong1VanBan <= Const.SO_LAN_XUAT_HIEN_MAX) {
                        if (abc.indexOf(wordString.get(idWord)) == -1) {
                            abc.add(wordString.get(idWord));
                            dict.get(idWord).soVanBanTuXuatHien++;
                            dict.get(idWord).word = wordString.get(idWord);
                            outText.append(idWord).append("\t").append((double) layTuTu1Dong(line).soLanXuatHienTrong1VanBan / tongSoTuTrongMotVanBan).append("\n");
                        }
                    }
                }
                ghiVaoFileChuan(file.substring(0, file.length() - 4) + "_chuan.txt", outText.toString());
            } catch (IOException ex) {
                Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return tongSoTuTrongMotVanBan;
    }
    // tính tfdif từ file tần xuất trong 1 văn bản và sắp xếp lại trật tự theo thứ
    // tự tăng dần của chỉ số của từ

    public String tinhTFDIFChoTungFile(String file, int label) {
        List<ID_Tfdif> wordTemp = new ArrayList<ID_Tfdif>();
        try {
            FileReader fr = new FileReader(file);
            BufferedReader reader = new BufferedReader(fr);
            String line = null;
            int id = 0;
            double tfdif = 0.0;
            int xuatHien = 0;
            while ((line = reader.readLine()) != null) {
                id = getIdCuaTu(line);
                xuatHien = dict.get(id).soVanBanTuXuatHien;
                tfdif = getTanSoCuaTu(line) * (Math.log10(((double) soVanBanHuanLuyen / (double) xuatHien)) + 1.0);
                wordTemp.add(new ID_Tfdif(id, tfdif));
            }
            Collections.sort(wordTemp); // sắp xếp theo id của từ 
            StringBuilder strOut = new StringBuilder(String.valueOf(label));
            for (int i = 0; i < wordTemp.size(); i++) {
                strOut.append(" ").append(wordTemp.get(i).id).append(":").append(wordTemp.get(i).tfdif);
            }
            return strOut.toString();
        } catch (IOException ex) {
            Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public String tinhTFDIFChoNhieuFile(String folder, int soFile, String firtNameFile, int label) {

//        this.soVanBanHuanLuyen = soFile;
        String file = "";
        StringBuilder str = new StringBuilder();
        for (int i = 1; i <= soFile; i++) {
            file = folder + firtNameFile + i + "_chuan.txt";
            str.append(tinhTFDIFChoTungFile(file, label)).append("\n");
        }
        ghiVaoFileChuan("model.txt", str.toString(), false);
        return str.toString();
    }

    public int getIdCuaTu(String line) {
        int indexOfSpace = line.lastIndexOf("\t");
        return Integer.parseInt(line.substring(0, indexOfSpace));
    }

    public double getTanSoCuaTu(String line) {
        int indexOfSpace = line.lastIndexOf("\t");
        return Double.parseDouble(line.substring(indexOfSpace + 1));
    }

    public Word layTuTu1Dong(String line) {
        int indexOfSpace = 0;
        String lineTemp = line.toLowerCase();
        char[] temp = lineTemp.toCharArray();
        for (int i = 0; i < temp.length; i++) {
            if ("\t".equalsIgnoreCase(String.valueOf(temp[i]))) {
                indexOfSpace = i;
                break;
            }
        }
        return new Word(lineTemp.substring(0, indexOfSpace), Integer.parseInt(lineTemp.substring(indexOfSpace + 1)));
    }

    public boolean ghiVaoFileChuan(String pathFile, String text) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(pathFile);
            writer.write(text);
            writer.close();
            return true;
        } catch (IOException ex) {
            Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                writer.close();
            } catch (IOException ex) {
                Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return false;
    }

    public boolean ghiVaoFileChuan(String pathFile, String text, boolean ghiDe) {
        try {
            if (ghiDe == false) {
                StringBuilder oldText = new StringBuilder("");
                String line = "";
                FileReader fr = new FileReader(pathFile);
                BufferedReader reader = new BufferedReader(fr);
                while ((line = reader.readLine()) != null) {
                    oldText.append(line).append("\n");
                }
                text = text + oldText.toString();
            }
            ghiVaoFileChuan(pathFile, text);
            return true;
        } catch (IOException ex) {
            Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;

    }

    public void HuanLuyen() {
//        this.start();
        readDiction();
        ghiVaoFileChuan("model.txt", "", true); // xóa file model cũ đi

        String folder_name = "data_train";
        docNhieuFileHuanLuyen(folder_name + "\\notthethao\\", "", Const.SO_FILE_NOT_THE_THAO);
        docNhieuFileHuanLuyen(folder_name + "\\thethao\\", "", Const.SO_FILE_THE_THAO);
        tinhTFDIFChoNhieuFile(folder_name + "\\notthethao\\", Const.SO_FILE_NOT_THE_THAO, "", Const.NOT_THE_THAO);
        tinhTFDIFChoNhieuFile(folder_name + "\\thethao\\", Const.SO_FILE_THE_THAO, "", Const.THE_THAO);
        ghiTuDienVaoFile();
        docTuDienTuFile();

    }

    public void ghiTuDienVaoFile() {
        try {
            FileOutputStream fos = new FileOutputStream(Const.FILE_TUDIEN);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            for (Word temp : dict) {
                oos.writeObject(temp);
            }
            oos.close();
            fos.close();
            fos = new FileOutputStream(Const.FILE_TUDIEN_STRING);
            oos = new ObjectOutputStream(fos);
            for (String temp : wordString) {
                oos.writeObject(temp);
            }
            System.out.println("Ghi từ điển thành công");
        } catch (Exception ex) {
        }
    }

    public void docTuDienTuFile() {
        List<Word> returnList = new ArrayList<Word>();
        List<String> stringdict = new ArrayList<String>();
        FileInputStream fis;
        ObjectInputStream ois;
        Object obj = null;
        try {
            fis = new FileInputStream(Const.FILE_TUDIEN);
            ois = new ObjectInputStream(fis);
            while (fis.available() > 0) {
                obj = ois.readObject();
                if (obj instanceof Word) {
                    Word a = (Word) obj;
                    returnList.add(a);
                }
            }
            ois.close();
            fis.close();
            fis = new FileInputStream(Const.FILE_TUDIEN_STRING);
            ois = new ObjectInputStream(fis);
            while (fis.available() > 0) {
                obj = ois.readObject();
                if (obj instanceof String) {
                    String a = (String) obj;
                    stringdict.add(a);
                }
            }
            ois.close();
            fis.close();
            this.dict = returnList;
            this.wordString = stringdict;
        } catch (Exception ex) {
            ex.printStackTrace();
            this.dict = returnList;
            this.wordString = stringdict;
        }
    }

    public boolean ghiWordVaoFile(String pathFile, List<Word> word) {

        try {
            FileOutputStream fos = new FileOutputStream(pathFile);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            if (word.size() <= 0) {
                return false;
            }
            for (Word temp : word) {
                oos.writeObject(temp);
            }
            oos.close();
            fos.close();
            return true;
        } catch (Exception ex) {
        }
        return false;
    }
    /*
     * Hàm đọc một 1 file chứa các Word và trả về 1 list chưa các Word đó
     * 
     * Para     :   - (String)      pathFile   path của file để đọc
     * return   :   - (List<Word>)  List chứa các đối tượng Word trong file
     *              -  null         Nếu có lỗi
     */

    public List<Word> docWordTuFile(String pathFile) {
        List<Word> returnList = new ArrayList<Word>();
        try {
            FileInputStream fis = new FileInputStream(pathFile);
            ObjectInputStream ois = new ObjectInputStream(fis);
            Object obj = null;
            while (fis.available() > 0) {
                obj = ois.readObject();
                if (obj instanceof Word) {
                    Word a = (Word) obj;
                    returnList.add(a);
                }
            }
            ois.close();
            fis.close();
        } catch (Exception ex) {
            System.out.println("Đã đọc hết file: " + pathFile);
        }
        return returnList;
    }

    public static void main(String[] args) {
        ChuanHoaFileHuanLuyen re = new ChuanHoaFileHuanLuyen();
        re.HuanLuyen();
        try {
            String train_argument[] = {"model.txt"};
            svm_train.main(train_argument);
        } catch (IOException ex) {
            Logger.getLogger(ChuanHoaFileHuanLuyen.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
